﻿using System;
using System.Diagnostics.Contracts;
using System.Runtime.InteropServices;

namespace O1.Kernel.Storage.Transactions
{
    [StructLayout(LayoutKind.Explicit)]
    public struct TxRecord : IEquatable<TxRecord>
    {
        public const int Size = Sz.CLR.Int64 * 2;

        [FieldOffset(0)]
        public readonly long Index;

        [FieldOffset(Sz.CLR.Int64)]
        public readonly long OwningTxId;

        public TxRecord(long index, long owningTxId)
            : this()
        {
            this.OwningTxId = owningTxId;
            this.Index = index;
        }

        public bool Equals(TxRecord other)
        {
            return other.Index == this.Index && other.OwningTxId == this.OwningTxId;
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2231:OverloadOperatorEqualsOnOverridingValueTypeEquals", Justification = "TODO later...")]
        public override bool Equals(object obj)
        {
            if (obj == null)
            {
                return false;
            }

            var t = obj.GetType();
            if (t == typeof(TxRecord))
            {
                return this.Equals((TxRecord)obj);
            }

            return false;
        }

        public override int GetHashCode()
        {
            return this.Index.GetHashCode() ^ this.OwningTxId.GetHashCode();
        }

        internal static unsafe TxRecord Read(byte[] buffer, int offset)
        {
            Contract.Requires(buffer != null);
            Contract.Requires(0 <= offset);
            Contract.Requires(offset + Size <= buffer.Length, ExceptionText.ValueBufferTooSmall);

            fixed (byte* p = &buffer[offset])
            {
                return *(TxRecord*)p;
            }
        }

        internal unsafe void Write(byte[] buffer, int offset)
        {
            Contract.Requires(buffer != null);
            Contract.Requires(0 <= offset);
            Contract.Requires(offset + Size <= buffer.Length, ExceptionText.ValueBufferTooSmall);

            fixed (byte* p = &buffer[offset])
            {
                *((TxRecord*)p) = this;
            }
        }
    }
}